﻿using CPPEI.Coolzon.Common;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
using System.Windows.Threading;
using Visifire.Charts;

namespace CPPEI.Coolzon.UI.DataPartLib
{
    /// <summary>
    /// DataPartChart.xaml 的交互逻辑
    /// --修改动画机制
    ///   做了修改，让动画只创建一次通过修改DataProgressValue属性来修改组件上datapoint的值，以完成动画
    /// 减少Animation对象的数量
    /// </summary>
    [System.ComponentModel.DisplayName("组合图表")]
    [XPartIcon("pack://application:,,,/CPPEI.Coolzon.UI.DataPartLib;component/Images/PartIcons/组合图表.png")]
    [XPart("DataPartChart", "组合图表")]
    public partial class DataPartChart : DataChartAxisBase
    {
        private List<ValueFlag> _dictDPValue;
        private Dictionary<string, string> dicSeriesLineStyle = new Dictionary<string, string>();


        private Visifire.Charts.DataSeries _emptyDataSeries = new Visifire.Charts.DataSeries();

        private int _index;
        /// <summary>
        /// 所有串所有项的总数目
        /// </summary>
        private int _dataSerieAllCount;
        private bool _isHasAreaChart = false;


        public double DataAnimationProgress
        {
            get
            {
                return (double)GetValue(DataAnimationProgressProperty);
            }
            set
            {
                SetValue(DataAnimationProgressProperty, value);
            }
        }

        public static DependencyProperty DataAnimationProgressProperty = DependencyProperty.Register("DataAnimationProgress",
            typeof(double),
            typeof(DataPartChart),
            new PropertyMetadata(default(double), OnDataAnimationProgressPropertyChangedCallback));

        private static void OnDataAnimationProgressPropertyChangedCallback(DependencyObject d, DependencyPropertyChangedEventArgs e)
        {
            DataPartChart dObject = d as DataPartChart;
            dObject.UpdateDataAnimationProcess();
        }

        /// <summary>
        /// 数据加载动画
        /// </summary>
        private DoubleAnimation _doubleAnimation;

        public DataPartChart()
        {
            _dictDPValue = new List<ValueFlag>();
            //XSeriesTypeDef = "series1:Column,series2:Line,series3:Line";
            XSeriesTypeDef = new SeriesTypeDef();
            XSeriesTypeDef["series1"] = "Column";
            XSeriesTypeDef["series2"] = "Line";
            XSeriesTypeDef["series3"] = "Line";

            XSeriesLineStyle = new SeriesLineStyle();
            XSeriesLineStyle["series1"] = "Solid";
            XSeriesLineStyle["series2"] = "Solid";
            XSeriesLineStyle["series3"] = "Solid";
            LegendEnabled = true;
            InitializeComponent();
        }
        protected override void SetDefaultDataResult()
        {
            Random random = new Random();
            ServiceProxy.DataServiceRef.DataSeries[] series = new ServiceProxy.DataServiceRef.DataSeries[3];
            for (int j = 1; j <= 3; j++)
            {
                series[j - 1] = new ServiceProxy.DataServiceRef.DataSeries();
                series[j - 1].Id = "series" + j;
                series[j - 1].Name = "series" + j;
                ServiceProxy.DataServiceRef.DataItem[] tmpItems = new ServiceProxy.DataServiceRef.DataItem[5];
                for (int i = 1; i <= 5; i++)
                {
                    tmpItems[i - 1] = new ServiceProxy.DataServiceRef.DataItem();
                    tmpItems[i - 1].Id = "data" + i;
                    tmpItems[i - 1].Name = "data" + i;
                    tmpItems[i - 1].Value = (random.NextDouble()*250).ToString("F2");
                }
                series[j - 1].DataItems = tmpItems;
            }
            DataResult = new ServiceProxy.DataServiceRef.DataResult();
            DataResult.DataSeries = series;
        }
        
        protected override void OnApplyXProperty()
        {
            base.OnApplyXProperty();
        }

        protected override void OnDataBinding(ServiceProxy.DataServiceRef.DataResult dataResult)
        {
            ClearAnimation();
            StopAnimation();
            _animationStoryboard = new Storyboard();
            _animationStoryboard.Completed += _animationStoryboard_Completed;
            _animationStoryboard.AccelerationRatio = 0.2d;
            _animationStoryboard.DecelerationRatio = 0.3d;
            _doubleAnimation = new DoubleAnimation(0, 1, new Duration(TimeSpan.FromSeconds(XDataAnimationDuration)));
            Storyboard.SetTarget(_doubleAnimation, this);
            Storyboard.SetTargetProperty(_doubleAnimation, new PropertyPath(DataPartChart.DataAnimationProgressProperty));
            _animationStoryboard.Children.Add(_doubleAnimation);

            _ctlChart.Series.Clear();
            _emptyDataSeries = null;

            double maxYValue = 0;
            double minYValue = 0;

            double max2ndYValue = 0;
            double min2ndYValue = 0;

            if (dataResult.DataSeries.Length > 0)
            {
                _index = 0;
                _dataSerieAllCount = 0;
                _dictDPValue.Clear();

                List<CPPEI.Coolzon.ServiceProxy.DataServiceRef.DataSeries> dataSeriesList = dataResult.DataSeries.ToList();
                for (int i = 0; i < dataSeriesList.Count; i++)
                {
                    Visifire.Charts.DataSeries vfdataSeries = new Visifire.Charts.DataSeries();
                    if (LineThickness != null)
                    {
                        vfdataSeries.LineThickness = LineThickness;
                    }
                    vfdataSeries.RenderAs = GetRender(dataSeriesList[i].Id);
                    vfdataSeries.Name = dataSeriesList[i].Name;
                    vfdataSeries.LegendText = dataSeriesList[i].Name;
                    vfdataSeries.Bevel = DataSeriesBevel;
                    vfdataSeries.ShowInLegend = LegendEnabled;
                    vfdataSeries.LineStyle = GetLineStyle(dataSeriesList[i].Id);
                    //设置Y轴类型 Primary或者Secondary
                    if (SeriesYAxisType != null && SeriesYAxisType.ContainsKey(dataSeriesList[i].Id))
                    {
                        vfdataSeries.AxisYType = (AxisTypes)Enum.Parse(typeof(AxisTypes), SeriesYAxisType[dataSeriesList[i].Id]);
                    }
                    if (vfdataSeries.RenderAs == RenderAs.Area)
                    {
                        _isHasAreaChart = true;
                    }

                    _dataSerieAllCount += dataSeriesList[i].DataItems.Length;

                    for (int itemIndex = 0; itemIndex < dataSeriesList[i].DataItems.Length; itemIndex++)
                    {
                        CPPEI.Coolzon.ServiceProxy.DataServiceRef.DataItem dataItem = dataSeriesList[i].DataItems[itemIndex];
                        DataPoint datapoint = new DataPoint();
                        datapoint.Name = dataItem.Name;
                        datapoint.LegendText = dataItem.Name;
                        datapoint.YValue = AxisYMinimum;
                        datapoint.ShowInLegend = LegendEnabled;
                        FormatDataPoint(vfdataSeries, datapoint, dataItem.Name);
                        SetDataPoint(datapoint);
                        vfdataSeries.DataPoints.Add(datapoint);

                        double dItemValue = Convertor.ToDouble(dataItem.Value);
                        if (vfdataSeries.AxisYType == AxisTypes.Secondary)
                        {
                            if (dItemValue > max2ndYValue)
                            {
                                max2ndYValue = dItemValue;
                            }
                            else if (dItemValue < min2ndYValue)
                            {
                                min2ndYValue = dItemValue;
                            }
                        }
                        else
                        {
                            if (dItemValue > maxYValue)
                            {
                                maxYValue = dItemValue;
                            }
                            else if (dItemValue < minYValue)
                            {
                                minYValue = dItemValue;
                            }
                        }
                        _dictDPValue.Add(new ValueFlag(datapoint.YValue, dItemValue, vfdataSeries, datapoint, itemIndex));
                    }
                    _ctlChart.Series.Add(vfdataSeries);
                }
            }

            _animationStoryboard.Begin(this);

            SetLegends(_ctlChart.Legends);

            ApplyChartColorPlate(_ctlChart, XColorPlate);

            AutoReviseYAxis(minYValue, maxYValue);
            AutoRevise2ndYAxis(min2ndYValue, max2ndYValue);
        }

        private void UpdateDataAnimationProcess()
        {
            double progress = this.DataAnimationProgress;
            if (!_isHasAreaChart)
            {
                foreach (ValueFlag vf in _dictDPValue)
                {
                    vf.DataPoint.YValue = vf.BeginValue + vf.DeltaValue * progress;
                }
            }
            else
            {
                int loopend = (int)(_dataSerieAllCount * progress);
                for (int i = _index; i < loopend; i++)
                {
                    _dictDPValue[i].DataSeries.DataPoints.RemoveAt(_dictDPValue[i].Index);
                    _dictDPValue[i].DataPoint.YValue = _dictDPValue[i].EndValue;
                    _dictDPValue[i].DataSeries.DataPoints.Insert(_dictDPValue[i].Index, _dictDPValue[i].DataPoint);
                }
                _index = loopend;
            }
        }

        protected override Chart GetChart()
        {
            return _ctlChart;
        }

        protected override RenderAs GetRender(string dataSeriesId)
        {
            if (XSeriesTypeDef.ContainsKey(dataSeriesId))
            {
                return (RenderAs)Enum.Parse(typeof(RenderAs), XSeriesTypeDef[dataSeriesId]);
            }
            else
            {
                return RenderAs.Column;
            }
        }
        protected override LineStyles GetLineStyle(string dataSeriesId)
        {
            //设置线的类型
            if (XSeriesLineStyle.ContainsKey(dataSeriesId))
            {
                return (LineStyles)Enum.Parse(typeof(LineStyles), XSeriesLineStyle[dataSeriesId]);
            }
            return LineStyles.Solid;
        }
    }
}
